package model;

import java.util.Collection;

public class Net {

	private final PlaceSet places;
	private final TransitionSet transitions;
	private final ArcSet arcs;
	
	public Net() {
		this.places = new PlaceSet();
		this.transitions = new TransitionSet();
		this.arcs = new ArcSet();
	}

	/**
	 * Adds a {@link Place} to this {@link Net}.
	 * If this {@link Net} already contains the provided {@link Place} nothing is done.
	 * @param place is the {@link Place} that is added.
	 */
	public void add(final Place place) {
		this.places.add(place);
	}

	/**
	 * Adds a {@link Transition} to this {@link Net}.
	 * If this {@link Net} already contains the provided {@link Transition} nothing is done.
	 * @param transition is the {@link Transition} that is added.
	 */
	public void add(final Transition transition) {
		this.transitions.add(transition);
	}

	/**
	 * Adds a new {@link Arc} to this {@link Net}.
	 * If this {@link Arc} already contains the provided {@link Arc} nothing is done.
	 * @param arc is the {@link Arc} that is added.
	 * @throws Error if the {@link Place} or {@link Transition} in the provided {@link Arc} is not in this {@link Net}.
	 */
	public void add(final Arc arc) {
		arc.accept(new ArcVisitor() {
			
			@Override
			public void visit(final TransitionPlaceArc transitionPlaceArc) {
				if(!Net.this.transitions.contains(transitionPlaceArc.getFrom())||
						!Net.this.places.contains(transitionPlaceArc.getTo())){
					throw new Error();
				}
			}
			
			@Override
			public void visit(final PlaceTransitionArc placeTransitionArc) {
				if(!Net.this.transitions.contains(placeTransitionArc.getTo())||
						!Net.this.places.contains(placeTransitionArc.getFrom())){
					throw new Error();
				}
			}
		});
		this.arcs.add(arc);
	}
	
	/**
	 * Returns an {@link ArcMatrix}, a {@link Transition} x {@link Place} matrix.
	 * The values of the returned {@link ArcMatrix} are:
	 * N = this {@link Net}
	 * P = the {@link PlaceSet} of this Net
	 * T = the {@link TransitionSet} of this Net.
	 * F = the {@link ArcSet} of this Net;
	 * p = an element of P.
	 * t = an element of t;
	 * Pre(N) = P x T = w(p,t) if (p,t) element of F else 0.
	 * @return the pre {@link ArcMatrix} of this {@link Net}.
	 */
	public ArcMatrix getPre(){
		final ArcMatrix result = new ArcMatrix(this.places.getVector(), this.transitions.getVector());
		for (final PlaceTransitionArc pta : this.arcs.getPlaceTransitionArcs()) {
			result.setValue(pta.getWeight(), pta.getFrom(), pta.getTo());
		}
		return result;
	}
	
	/**
	 * Returns an {@link ArcMatrix}, a {@link Transition} x {@link Place} matrix.
	 * The values of the returned {@link ArcMatrix} are:
	 * N = this {@link Net}
	 * P = the {@link PlaceSet} of this Net
	 * T = the {@link TransitionSet} of this Net.
	 * F = the {@link ArcSet} of this Net;
	 * p = an element of P.
	 * t = an element of t;
	 * Post(N) = P x T = w(t,p) if (t,p) element of F else 0.
	 * @return the pre {@link ArcMatrix} of this {@link Net}.
	 */
	public ArcMatrix getPost(){
		final ArcMatrix result = new ArcMatrix(this.places.getVector(), this.transitions.getVector());
		for (final TransitionPlaceArc tpa : this.arcs.getTransitionPlaceArcs()) {
			result.setValue(tpa.getWeight(), tpa.getTo(), tpa.getFrom());
		}
		return result;
	}

	public Collection<Transition> getTransitions() {
		return this.transitions.getVector();
	}	
	
	
	
}